//!
use std::os;
-use util::config::{Config, ConfigValue};
-use core::{MultiShell, Source, SourceId, PackageSet, Target, PackageId, resolver};
+use std::collections::HashMap;
+
use core::registry::PackageRegistry;
+use core::{MultiShell, Source, SourceId, PackageSet, Target, PackageId, resolver};
use ops;
use sources::{PathSource};
-use util::{CargoResult, Wrap, config, internal, human};
+use util::config::{Config, ConfigValue};
+use util::{CargoResult, Wrap, config, internal, human, ChainError};
pub struct CompileOptions<'a> {
pub update: bool,
try!(shell.warn(format!("unused manifest key: {}", key)));
}
- let override_ids = try!(source_ids_from_config());
+ let user_configs = try!(config::all_configs(os::getcwd()));
+ let override_ids = try!(source_ids_from_config(&user_configs));
let source_ids = package.get_source_ids();
let (packages, resolve) = {
}).collect::<Vec<&Target>>();
let mut config = try!(Config::new(*shell, update, jobs, target));
+ try!(scrape_target_config(&mut config, &user_configs));
try!(ops::compile_targets(env.as_slice(), targets.as_slice(), &package,
&PackageSet::new(packages.as_slice()), &resolve, &mut config));
Ok(test_executables)
}
-fn source_ids_from_config() -> CargoResult<Vec<SourceId>> {
- let configs = try!(config::all_configs(os::getcwd()));
-
+fn source_ids_from_config(configs: &HashMap<String, config::ConfigValue>)
+ -> CargoResult<Vec<SourceId>> {
debug!("loaded config; configs={}", configs);
let config_paths = configs.find_equiv(&"paths").map(|v| v.clone());
let config_paths = config_paths.unwrap_or_else(|| ConfigValue::new());
- let paths: Vec<Path> = match *config_paths.get_value() {
- config::String(_) => return Err(internal("The path was configured as \
- a String instead of a List")),
- config::Table(_) => return Err(internal("The path was configured as \
- a Table instead of a List")),
- config::List(ref list) => {
- list.iter().map(|path| Path::new(path.as_slice())).collect()
- }
+ let paths = try!(config_paths.list().chain_error(|| {
+ internal("invalid configuration for the key `path`")
+ }));
+
+ Ok(paths.iter().map(|p| SourceId::for_path(&Path::new(p.as_slice()))).collect())
+}
+
+fn scrape_target_config(config: &mut Config,
+ configs: &HashMap<String, config::ConfigValue>)
+ -> CargoResult<()> {
+ let target = match configs.find_equiv(&"target") {
+ None => return Ok(()),
+ Some(target) => try!(target.table().chain_error(|| {
+ internal("invalid configuration for the key `target`")
+ })),
+ };
+ let target = match config.target() {
+ None => target,
+ Some(triple) => match target.find_equiv(&triple) {
+ None => return Ok(()),
+ Some(target) => try!(target.table().chain_error(|| {
+ internal(format!("invalid configuration for the key \
+ `target.{}`", triple))
+ })),
+ },
};
- Ok(paths.iter().map(|p| SourceId::for_path(p)).collect())
+ match target.find_equiv(&"ar") {
+ None => {}
+ Some(ar) => {
+ config.set_ar(try!(ar.string().chain_error(|| {
+ internal("invalid configuration for key `ar`")
+ })).to_string());
+ }
+ }
+
+ match target.find_equiv(&"linker") {
+ None => {}
+ Some(linker) => {
+ config.set_linker(try!(linker.string().chain_error(|| {
+ internal("invalid configuration for key `ar`")
+ })).to_string());
+ }
+ }
+
+ Ok(())
}
into.push("--out-dir".to_string());
into.push(cx.dest(plugin).display().to_string());
- match cx.config.target() {
- Some(target) if !plugin => {
- into.push("--target".to_string());
- into.push(target.to_string());
+ if !plugin {
+ fn opt(into: &mut Vec<String>, key: &str, prefix: &str,
+ val: Option<&str>) {
+ match val {
+ Some(val) => {
+ into.push(key.to_string());
+ into.push(format!("{}{}", prefix, val));
+ }
+ None => {}
+ }
}
- _ => {}
+
+ opt(into, "--target", "", cx.config.target());
+ opt(into, "-C", "ar=", cx.config.ar());
+ opt(into, "-C", "linker=", cx.config.linker());
}
}
shell: &'a mut MultiShell,
jobs: uint,
target: Option<String>,
+ linker: Option<String>,
+ ar: Option<String>,
}
impl<'a> Config<'a> {
shell: shell,
jobs: jobs.unwrap_or(os::num_cpus()),
target: target,
+ ar: None,
+ linker: None,
})
}
pub fn target<'a>(&'a self) -> Option<&'a str> {
self.target.as_ref().map(|t| t.as_slice())
}
+
+ pub fn set_ar(&mut self, ar: String) { self.ar = Some(ar); }
+
+ pub fn set_linker(&mut self, linker: String) { self.linker = Some(linker); }
+
+ pub fn linker<'a>(&'a self) -> Option<&'a str> {
+ self.linker.as_ref().map(|t| t.as_slice())
+ }
+ pub fn ar<'a>(&'a self) -> Option<&'a str> {
+ self.ar.as_ref().map(|t| t.as_slice())
+ }
}
#[deriving(Eq,PartialEq,Clone,Encodable,Decodable)]
Ok(())
}
+
+ pub fn string<'a>(&'a self) -> CargoResult<&'a str> {
+ match self.value {
+ Table(_) => Err(internal("expected a string, but found a table")),
+ List(_) => Err(internal("expected a string, but found a list")),
+ String(ref s) => Ok(s.as_slice()),
+ }
+ }
+
+ pub fn table<'a>(&'a self) -> CargoResult<&'a HashMap<String, ConfigValue>> {
+ match self.value {
+ String(_) => Err(internal("expected a table, but found a string")),
+ List(_) => Err(internal("expected a table, but found a list")),
+ Table(ref table) => Ok(table),
+ }
+ }
+
+ pub fn list<'a>(&'a self) -> CargoResult<&'a [String]> {
+ match self.value {
+ String(_) => Err(internal("expected a list, but found a string")),
+ Table(_) => Err(internal("expected a list, but found a table")),
+ List(ref list) => Ok(list.as_slice()),
+ }
+ }
}
impl ConfigValueValue {
#![cfg(target_os = "macos")]
use std::os;
+use std::path;
use support::{project, execs, basic_bin_manifest};
+use support::{RUNNING, COMPILING};
use hamcrest::{assert_that, existing_file};
use cargo::util::process;
process(foo.target_bin(target, "main")),
execs().with_status(0));
})
+
+test!(linker_and_ar {
+ let target = alternate();
+ let p = project("foo")
+ .file(".cargo/config", format!(r#"
+ [target.{}]
+ ar = "my-ar-tool"
+ linker = "my-linker-tool"
+ "#, target).as_slice())
+ .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
+ .file("src/foo.rs", r#"
+ use std::os;
+ fn main() {
+ assert_eq!(os::consts::ARCH, "x86");
+ }
+ "#);
+
+ assert_that(p.cargo_process("cargo-build").arg("--target").arg(target)
+ .arg("-v"),
+ execs().with_status(101)
+ .with_stdout(format!("\
+{running} `rustc src/foo.rs --crate-name foo --crate-type bin \
+ --out-dir {dir}{sep}target{sep}{target} \
+ --target {target} \
+ -C ar=my-ar-tool -C linker=my-linker-tool \
+ -L {dir}{sep}target{sep}{target} \
+ -L {dir}{sep}target{sep}{target}{sep}deps`
+{compiling} foo v0.5.0 (file:{dir})
+",
+ running = RUNNING,
+ compiling = COMPILING,
+ dir = p.root().display(),
+ target = target,
+ sep = path::SEP,
+ ).as_slice()));
+})